#pragma once

#include <type_traits>

namespace sirtet
{

template <typename Num>
struct Rect final
{
    static_assert(std::is_arithmetic_v<Num>);

  private:
    Num x, y;
    Num width, height;

  public:
    Rect(Num x, Num y, Num width, Num height) : x(x), y(y), width(width), height(height)
    {
    }

    static Rect from_corners(Num right, Num top, Num left, Num bottom)
    {
        return Rect(left, top, right - left, bottom - top);
    }

    Num get_x() const
    {
        return x;
    }
    Num &get_x_mut()
    {
        return x;
    }
    void set_x(Num x)
    {
        this->x = x;
    }

    Num get_y() const
    {
        return y;
    }
    Num &get_y_mut()
    {
        return y;
    }
    void set_y(Num y)
    {
        this->y = y;
    }

    Num get_width() const
    {
        return width;
    }
    Num &get_width_mut()
    {
        return width;
    }
    void set_width(Num width)
    {
        this->width = width;
    }

    Num get_height() const
    {
        return height;
    }
    Num &get_height_mut()
    {
        return height;
    }
    void set_height(Num height)
    {
        this->height = height;
    }

    Num get_left() const
    {
        return x;
    }
    void set_left(Num left)
    {
        x = left;
    }
    Num get_right() const
    {
        return x + width;
    }
    void set_right(Num right)
    {
        width = right - x;
    }
    Num get_top() const
    {
        return y;
    }
    void set_top(Num top)
    {
        y = top;
    }
    Num get_bottom() const
    {
        return y + height;
    }
    void set_bottom(Num bottom)
    {
        height = bottom - y;
    }
};

} // namespace sirtet